<template>
  <div class="department-container">
    <div class="app-container">
      <el-card>
        <!-- 用一个行列布局 -->
        <el-row type="flex" justify="space-between" align="middle" style="height: 40px">
          <el-col :span="20">
            <span>江苏传智播客教育科技股份有限公司</span>
          </el-col>
          <el-col :span="4">
            <el-row type="flex" justify="end">
              <!-- 两个内容 -->
              <el-col>负责人</el-col>
              <el-col>操作</el-col>
            </el-row>
          </el-col>
        </el-row>
        <!-- 这个tree组件默认识别的字段为label和children，如果后端返回的数据不叫这个，需要我们自定义识别出来
        :props="defaultProps"：修改tree组件识别字段的名称
        default-expand-all：是否默认展开所有子节点
        
        如何给组件传递属性：
          1、不加冒号  name = 'this is name'这永远都是一个字符串
          2、加冒号   ：
            使用当前组件实例身上的属性（data和props上的数据）
            直接识别类型的数据  boolean number 数组 对象
          default-expand-all：true，不加冒号会进行隐式转换为Boolean类型
        -->
        <el-tree :data="list" :default-expand-all="true" :props="defaultProps">
          <!-- data是固定的吗：是，解构赋值的写法 
            #default=“scope” :这个scope不是固定的，类似于函数的形参
          我们用组件都是写好了一半，容许我们传入参数，也给我们抛出了现成参数
          如果我们想看data或node的调试：
            1、差值渲染
            2、设计一个小点击事件，来打印出来看看
        -->
          <!-- data：是作用域插槽抛出来的参数，代表的是当前数据的中每一个对象 -->
          <template #default="{ data }">
            <el-row
              type="flex"
              justify="space-between"
              align="middle"
              style="height: 40px; width: 100%;"
            >
              <el-col :span="20">
                <span>{{ data.name }}</span>
              </el-col>
              <el-col :span="4">
                <el-row type="flex" justify="end">
                  <!-- 两个内容 -->
                  <el-col>{{ data.manager }}</el-col>
                  <el-col>
                    <!-- 下拉菜单 element -->
                    <el-dropdown>
                      <span> 操作<i class="el-icon-arrow-down" /> </span>
                      <el-dropdown-menu slot="dropdown">
                        <el-dropdown-item @click.native="addDepartment(data.id)">添加子部门</el-dropdown-item>
                        <el-dropdown-item @click.native="editDepartment(data.id)">编辑部门</el-dropdown-item>
                        <el-dropdown-item @click.native="delDepartment(data.id)">删除部门</el-dropdown-item>
                      </el-dropdown-menu>
                    </el-dropdown>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-tree>
      </el-card>   
    </div>
    <!-- @close="closeDialog"
      @open="openDialog"
      这两个方法是dialog提示框的关闭和打开事件，当点击弹框的X和空白区会触发closeDialog这个函数
      只要弹框打开，就会触发openDialog这个函数 -->
    <!-- 添加子部门弹框 -->
    <el-dialog
      title="提示"
      :visible="dialogVisible"
      width="30%"
      @close="closeDialog"
      @open="openDialog"
    >
      <!-- 表单和按钮使用具名插槽的作用：
      （1）解构语义化 更清晰
      （2）不写的 就相当于被一个默认插槽包裹着 -->
      <template #default>
        <el-form ref="addForm" label-width="120px" :model="addDeparmentList" :rules="rules">
          <el-form-item label="部门名称" prop="name">
            <el-input v-model="addDeparmentList.name" style="width:80%" placeholder="1-50个字符" />
          </el-form-item>
          <el-form-item label="部门编码" prop="code">
            <el-input v-model="addDeparmentList.code" style="width:80%" placeholder="1-50个字符" />
          </el-form-item>
          <el-form-item label="部门负责人" placeholder="请选择" prop="manager">
            <!-- label:下拉框的文本显示
            value:选中的那一项value值会自动绑定到addDeparmentList.manager,提交给后端
             -->
            <el-select v-model="addDeparmentList.manager" style="width:80%">
              <el-option
                v-for="item in managerList"
                :key="item.id"
                :label="item.username"
                :value="item.username"
              />
            </el-select> 
          </el-form-item>
          <el-form-item label="部门介绍" prop="introduce">
            <el-input v-model="addDeparmentList.introduce" style="width:80%" placeholder="1-30个字符" />
          </el-form-item>
        </el-form>
      </template>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click.native="addDep">确 定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 编辑子部门弹框 -->
    
  </div>
</template>
// // 新增实现：
//   /*
//   1、点击按钮，弹框打开
//   2、在弹框中准备表单
//   3、表单验证
//   4、调用接口，新增部门
//   5、提示用户，关闭弹框，更新列表，重置表单
  
//   */


/**编辑实现
  1、点击编辑部门，弹框显示
  2、数据回显,调用当前点击项的接口进行数据回填
  3、编辑表单，提交数据
  4、调用更新列表接口
  5、弹框关闭
**/


/**删除部门
  1、询问用户 this.$comfirm
  2、调用删除接口
  3、提示用户删除成功，更新列表
**/
<script>
import {fetchDepartmentAPI, getManagerListAPI, addDepartmentAPI, getDepartmentAPI, updateDepartmentAPI, delDepartmentAPI} from '@/api/department'
import tree from '@/utils/tree'
// 1、获取列表渲染
// 思路：1、定义响应式数据--->2、调用接口获取数据 ---->将数据赋值给响应式数据
// created mounted 在当前的场景下，写到这两个里面毫无差别
// mounted：dom可用，比如：echarts图标渲染   百度地图(在里面必须要提前准备好DOM)
// 服务端渲染:没有mounted钩子函数
// 为什么请求要单独封装一个函数，而不是直接写在mounted里面？
// （1）结构清晰，生命周期钩子函数不应该包含太多逻辑代码，它最好是代码
// （2）方便复用，在这个函数里面封装好更新列表的所有逻辑【参数二次处理，数据获取到赋值】

export default {
  data(){
    // 自定义验证（code不能和已经存在的code重复）
    // 1、给code添加一个新的规则，自定义校验函数
    // 2、写不可重复的规则
    const codeVlidate = (rule, value, callback) => {
      let  codeLists=[]
      if (!this.addDeparmentList.id){
        // 如果是新增的弹框，则将所有的code放到一个新的数组中，目的就是对数组进行一个备份
        codeLists =  this.code
      } else {
        // 如果是编辑的弹框，就在所有的部门列表code中过滤掉编辑表单code回显的值，意思就是你输入当前表单一样的值是没有影响的，但是如果你输入与其他code一样就重复了
        codeLists =   this.code.filter(item => item!==this.oldCode)
      }
      if (codeLists.includes(value)){
        callback(new Error('code不能重复'))
      } else {
        callback()
      }
    }
    return {
      
      
      name: 'Department',
      oldCode: '',
      code: [],
      list: [{
        name: '财务部',
        
        children: [
          {
            name: '财务核算部'
          },
          {
            name: '税务核算部'
          }
        ]
      }],
      defaultProps: {
        label: 'name'
      },
      dialogVisible: false,
      // 提交给后端的数据
      addDeparmentList: {
        code: '',
        name: '',
        manager: '',
        introduce: '',
        
        // 这个pid是指父级部门，要给哪个父级部门添加子级
        pid: ''
      },
      // 表单验证
      rules: {
        code: [
          // 按顺序校验
          {required: true, message: '部门编码必填', trigger: 'blur'},
          {min: 1, max: 50, message: '部门编码长度为1-50', trigger: 'blur'},
          {validator: codeVlidate, trigger: 'blur'}
        ],
        name: [
          {required: true, message: '部门名称必填', trigger: 'blur'},
          {min: 1, max: 50, message: '部门名称长度为1-50', trigger: 'blur'}
        ],
        manager: [
          {required: true, message: '负责人名称必填', trigger: 'change'}
         
        ],
        introduce: [
          {required: true, message: '部门介绍必填', trigger: 'blur'},
          {min: 1, max: 300, message: '部门编码长度为1-300', trigger: 'blur'}
        ]
      },
      // 存放部门负责人
      managerList: []
      // 存放回显表单的数据
     
    }
  },
  mounted(){
    this.getList()
  },
  methods: {
    // 获取部门列表
    async getList(){
      // response响应数据已经优化为拿到response.data了，所以这里的res相当于已经是后端返回的数据了，我们直接拿到这个数据的depts即可
      const res =  await fetchDepartmentAPI()
      // 目标：把后端的你返回的平铺数组转为组件需要的树形数组
      // 解决问题：1.直接搜方案，2.自己写
      this.list = tree(res.depts)
      this.list.forEach(item => {
        this.code.push(item.code)

      })
      const arr =[1, 2, 2]
      const b = arr
      console.log(b.push(5))
      console.log(b)
      console.log(arr)
     
      
    },
    // 打开添加部门弹窗
    addDepartment(id){
      // 不管点击哪个添加部门，都可以拿到父级的部门pid
      this.addDeparmentList.pid = id
      this.dialogVisible = true
    },
    // 点击X,和空白区域关闭弹框
    closeDialog(){
      this.dialogVisible = false
      // 关闭弹框的时候就清空表单
      this.$refs.addForm.resetFields()
    },
    // 开启弹框的时候，获取部门负责人列表
    async openDialog(){
      const res = await getManagerListAPI()
      this.managerList = res
    },
    // 添加和编辑部门子级
    addDep(){
      // 兜底校验
      this.$refs.addForm.validate(async valid => {
        if (valid){
          // 这里由于添加部门和编辑部门是公用一个弹框的，所以要判断到底调用哪个接口，关键看表单中有没有id,
          // 如果有就调用编辑的接口
          // 如果验证通过
          if (this.addDeparmentList.id) {
            // 如果有id就调用编辑接口
            await updateDepartmentAPI(this.addDeparmentList)
          } else {
            // 如果没有就调用新增接口,   // （1）则发送请求，添加子部门
            await addDepartmentAPI(this.addDeparmentList)
          }
       
          
          // （2）提示用户新增成功
          this.$message.success(`${this.addDeparmentList.id?'编辑':'新增'}部门成功`)
          // (3)关闭弹窗
          this.dialogVisible = false
          // （4）更新列表
          this.getList()
          // （5）清空表单，这个有点坑，只能清除双向绑定的数据，像id还没有被清除
          this.$refs.addForm.resetFields()
          this.resetForm()

        }

      })
    },
    // 清除表单
    resetForm(){
      this.addDeparmentList={
        code: '',
        name: '',
        manager: '',
        introduce: ''
      } 
    },
    // 弹出编辑部门框，并获取到获取到指定id的部门信息并数据回填
    async editDepartment(id){
      this.dialogVisible = true
      // 然后根据id获取到对应的部门信息

      const res = await getDepartmentAPI(id)
      this.addDeparmentList = res
      // 暂存编辑时回显的code
      this.oldCode = res.code
    },
    async delDepartment(id){
      this.$confirm('确认删除此部门吗？, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        await delDepartmentAPI(id)
        this.$message.success('删除成功')
        this.getList()
      }).catch(() => {
              
      });
      
    }


  }
}
</script>

<style>
</style>
